package com.kedacom.demo.emailgateway.core.annotation;

import java.lang.reflect.Field;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.ReflectionUtils;

public class AnnotationBeanPostProcessor extends PropertyPlaceholderConfigurer implements BeanPostProcessor,
		InitializingBean {

	private java.util.Properties pros;

	@SuppressWarnings("rawtypes")
	private Class[] enableClassList = { String.class };

	@SuppressWarnings("rawtypes")
	public void setEnableClassList(Class[] enableClassList) {
		this.enableClassList = enableClassList;
	}

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		Field[] fields = bean.getClass().getDeclaredFields();
		for (Field field : fields) {
			if (field.isAnnotationPresent(Properties.class)) {
				if (logger.isDebugEnabled()) {
					StringBuilder sb = new StringBuilder();
					sb.append(" ========= ").append(field.getType()).append(" ============ ").append(field.getName())
							.append(" ============ ").append(field.isAnnotationPresent(Properties.class));
					logger.debug(sb.toString());
				}
				if (filterType(field.getType().toString())) {
					Properties p = field.getAnnotation(Properties.class);
					try {
						// StringBuilder sb = new StringBuilder();
						// sb.append("set").append(StringUtils.upperCase(field.getName().substring(0,
						// 1)))
						// .append(field.getName().substring(1,
						// field.getName().length()));
						//
						// Method method =
						// bean.getClass().getMethod(sb.toString(),
						// String.class);
						// method.invoke(bean, pros.getProperty(p.name()));
						// 本来我是通过set方法来把properties文件中的值注入到对应的属性上去的，后来downpour提供了更好的方案，就是下面这两行代码，虽然这样做破坏了private的功能，同时破坏了封装，但是确实节省了很多代码，建议大家在业务代码中不要这样做，如果做框架代码可以考虑一下。
						ReflectionUtils.makeAccessible(field);
						field.set(bean, pros.getProperty(p.name()));
					} catch (Exception e) {
						logger.error(" --- ", e);
					}
				}
			}
		}
		return bean;
	}

	@SuppressWarnings("rawtypes")
	private boolean filterType(String type) {
		if (type != null) {
			for (Class c : enableClassList) {
				if (c.toString().equals(type)) {
					return true;
				}
			}
			return false;
		} else {
			return true;
		}
	}

	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	public void afterPropertiesSet() throws Exception {
		pros = mergeProperties();
	}
}
